package cn.lg.soar.common.algorithm;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import static cn.lg.soar.common.util.data.DataUtil.BASE64DE;
import static cn.lg.soar.common.util.data.DataUtil.BASE64EN;

/**
 * 私钥编码器
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class RSAPrivateKeyCoder {

    private final PrivateKey privateKey;
    private Cipher encoder;
    private Cipher decoder;

    public RSAPrivateKeyCoder(byte[] privateKey) {
        try {
            this.privateKey = KeyFactory.getInstance(RSAUtils.RSA)
                    .generatePrivate(new PKCS8EncodedKeySpec(privateKey));
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 加密
     * @param data 数据
     * @return
     */
    public byte[] encrypt(byte[] data) {
        if (null == this.encoder) {
            try {
                Cipher cipher = Cipher.getInstance(RSAUtils.RSA);
                cipher.init(Cipher.ENCRYPT_MODE, this.privateKey);
                this.encoder = cipher;
            } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) {
                throw new AlgorithmException(e);
            }
        }

        try {
            return this.encoder.doFinal(data);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new AlgorithmException(e);
        }
    }

    /**
     * 解密
     * @param data 数据
     * @return
     */
    public byte[] decrypt(byte[] data) {
        if (null == this.decoder) {
            try {
                Cipher cipher = Cipher.getInstance(RSAUtils.RSA);
                cipher.init(Cipher.DECRYPT_MODE, this.privateKey);
                this.decoder = cipher;
            } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) {
                throw new AlgorithmException(e);
            }
        }

        try {
            return this.decoder.doFinal(data);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new AlgorithmException(e);
        }
    }

    /**
     * 加密
     * @param data 数据
     * @return
     */
    public String encryptToBase64(byte[] data) {
        return BASE64EN.encodeToString(
                this.encrypt(data)
        );
    }

    /**
     * 解密
     * @param data 数据
     * @return
     */
    public byte[] decryptOfBase64(String data) {
        return this.decrypt( BASE64DE.decode(data) );
    }

}
